/*
 * This file is part of MonoSettlers.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://opensettlers.codeplex.com/
 */
#ifndef OPENCLOSEMAP_H_
#define OPENCLOSEMAP_H_

#include <vector>

class COpenCloseMap
{
private:
	PATHFINDER_NODE** m_Map;
    int Width;
    int Height;
    int Count;
	int SizeShift;

public:
    LPPATHFINDER_NODE Get(int x, int y)
    {
        return m_Map[x + (y << SizeShift)];
    }

	void Set(int x, int y, LPPATHFINDER_NODE inNewValue)
    {
        m_Map[x + (y << SizeShift)] = inNewValue;
    }

    LPPATHFINDER_NODE Get(POINT point)
    {
        return m_Map[point.x + (point.y << SizeShift)];
    }

    bool IsEmpty()
    {
        return Count == 0;
    }

    COpenCloseMap(int inSize)
    {
		static const double log2Factor = 1.0/std::log(2.0);

		SizeShift = (int)std::floor((std::log((double)inSize) * log2Factor) + 0.5);

		if((int)std::pow(2, (double)SizeShift) != inSize)
			throw "Size is not a power of two!";

        m_Map = new LPPATHFINDER_NODE[inSize * inSize];
        Width = inSize;
        Height = inSize;
    }

	~COpenCloseMap()
	{
		if(m_Map != NULL){
			delete m_Map;

			m_Map = NULL;
		}
	}

    void Add(LPPATHFINDER_NODE inValue)
    {
        LPPATHFINDER_NODE item = Get(inValue->X, inValue->Y);

        Count++;
        Set(inValue->X, inValue->Y, inValue);
    }

    bool IsSet(POINT inValue)
    {
		return Get(inValue.x, inValue.y) != NULL;
    }

    bool Contains(LPPATHFINDER_NODE inValue)
    {
        LPPATHFINDER_NODE item = Get(inValue->X, inValue->Y);

        if (item == NULL)
            return false;

        return true;
    }

    void Remove(LPPATHFINDER_NODE inValue)
    {
        LPPATHFINDER_NODE item = Get(inValue->X, inValue->Y);

        Count--;
        Set(inValue->X, inValue->Y, NULL);
    }

    void Clear()
    {
        Count = 0;
        memset(m_Map, 0, sizeof(LPPATHFINDER_NODE) * Width * Height);
    }
};

#endif